using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using ALib;
using AxTWSLib;
using TWSLib;
using _DTwsEvents_historicalDataEventHandler = AxTWSLib._DTwsEvents_historicalDataEventHandler;

namespace TradingPlatform.IB.Operations
{
    public class PlaceOrder
    {
        //private readonly AxTws _tws;
        private Comm _comm;

        private readonly OrderManagementDb _orderManagementDb;

        public OrderManagementDb OrderManagementDb
        {
            get { return _orderManagementDb; }
        } 


        public PlaceOrder(Comm comm, OrderManagementDb orderManagementDb)
        {
            //_tws = tws;
            _comm = comm;
            //_tws.orderStatus += new AxTWSLib._DTwsEvents_orderStatusEventHandler(_tws_orderStatus);
            _orderManagementDb = orderManagementDb;
        }

        public void RequestToPlaceMarketOrder(string exchange, string secType, string symbol, string expiry, string currency, int orderId, int quantity)
        {
            GoodValue.AssertDouble(quantity);
            GoodValue.Assert(quantity != 0);

            //IContract contract = _tws.createContract();
            //contract.exchange = exchange;
            //contract.secType = secType;
            //contract.symbol = symbol;
            //contract.expiry = expiry;
            //contract.currency = currency;

            //IOrder order = _tws.createOrder();
            //order.orderId = orderId;
            //order.orderType = "MKT";
            //order.action = quantity > 0 ? "BUY" : "SELL";
            //order.totalQuantity = Math.Abs(quantity);
            //order.timeInForce = "DAY";
            //order.transmit = 1;
            //order.overridePercentageConstraints = 1;

            //_tws.placeOrderEx(orderId,contract, order);

            _comm.InsertOrder(orderId, symbol, 0, quantity, CommOrderTypeField.Type.Mkt);

            string tickerName = TickerNameAndId.ToTickerName(exchange, secType, symbol, expiry, currency);
            _orderManagementDb.SendOrder(tickerName, orderId, double.NaN, quantity);
        }

        public void RequestToPlaceLimitOrder(string exchange, string secType, string symbol, string expiry, string currency, int orderId, double price, int quantity)
        {
            GoodValue.AssertDouble(price);
            GoodValue.Assert(price > 0);

            GoodValue.AssertDouble(quantity);
            GoodValue.Assert(quantity != 0);

            //IContract contract = _tws.createContract();
            //contract.exchange = exchange;
            //contract.secType = secType;
            //contract.symbol = symbol;
            //contract.expiry = expiry;
            //contract.currency = currency;

            //IOrder order = _tws.createOrder();
            //order.orderId = orderId;
            //order.orderType = "LMT";
            //order.action = quantity > 0 ? "BUY" : "SELL";
            //order.lmtPrice = price;
            //order.totalQuantity = Math.Abs(quantity);
            //order.timeInForce = "DAY";
            //order.transmit = 1;

            //_tws.placeOrderEx(orderId, contract, order);
            _comm.InsertOrder(orderId, symbol, price, quantity, CommOrderTypeField.Type.Lmt);

            string tickerName = TickerNameAndId.ToTickerName(exchange, secType, symbol, expiry, currency);
            _orderManagementDb.SendOrder(tickerName, orderId, price, quantity);
        }

        public void CancelOrder(int orderId)
        {
            _comm.CancelOrder(orderId);
            //_tws.cancelOrder(orderId);
        }

        public void UpdateOrder(OrderStatusMessage msg)
        {
            CommOrderStatusField.Status status = (CommOrderStatusField.Status) msg.OrderStatusField.IntValue;
            int orderID = msg.OrderIDField.IntValue;
            int sz = msg.FilledSzField.IntValue;
            double px = msg.FilledPxField.DoubleValue;
            int remaining = msg.RemainSzField.IntValue;
            switch (status)
            {
                case CommOrderStatusField.Status.Canceled:
                    _orderManagementDb.CancelOrder(orderID);
                    break;
                case CommOrderStatusField.Status.Filled:
                case CommOrderStatusField.Status.PendingFill:
                case CommOrderStatusField.Status.PartialFill:
                    _orderManagementDb.FillOrder_TotalRemaining(orderID, remaining);
                    break;
                default:
                    break;
            }
        }

        //void _tws_orderStatus(object sender, _DTwsEvents_orderStatusEvent e)
        //{
        //    // Confirmed, that e.filled is the total filled, not number of filled.
        //    // When partially filled, the status is "Submitted". Only when all orders are filled, the status will be "Filled"

        //    int orderId = e.id;

        //    string outputString = string.Join(",",
        //                new string[]
        //                    {
        //                        e.clientId.ToString(), e.id.ToString(), e.filled.ToString(), e.lastFillPrice.ToString(),
        //                        e.remaining.ToString(), e.status, e.whyHeld
        //                    });
        //    Logger.WriteLine("OrderStatus.csv", outputString);

        //    string statusInLowerCase = e.status.ToLower();
        //    switch (statusInLowerCase)
        //    {
        //        case KeyWordsOrderStatus.Cancelled:
        //            _orderManagementDb.CancelOrder(orderId);
        //            break;
        //        case KeyWordsOrderStatus.Submitted:
        //        case KeyWordsOrderStatus.Filled:
        //            // Should use remaining.
        //            int remaining = e.remaining;
        //            GoodValue.Assert(remaining >= 0);
        //            _orderManagementDb.FillOrder_TotalRemaining(orderId, remaining);
        //            break;
        //        default:
        //            break;
        //    }
        //    Logger.Save();
        //}
    }
}